﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ZOIL.DataModel;
using ZOIL.Framework.Presentation;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Threading;
using System.IO;

namespace ZOIL.Library.Components
{
    /// <summary>
    /// Interaction logic for TopicCardView.xaml
    /// </summary>
    [ViewFor(typeof(TopicCard), "default")]
    public partial class TopicCardView : ZComponent
    {
        private static Random _rnd = new Random();

        public static List<TopicCardView> allInstances = new List<TopicCardView>();

        ~TopicCardView()
        {
            allInstances.Remove(this);
        }

        public TopicCardView()
        {
            InitializeComponent();
            allInstances.Add(this);
            Loaded += new RoutedEventHandler(TopicCardView_Loaded);
            //AddHandler(Contacts.ContactDownEvent, new ContactEventHandler(OnContactDown), true);
        }

        
        //public void OnContactDown(object sender, ContactEventArgs e)
        //{
        //    // switch background images

        //    TopicCardView icv = (sender as TopicCardView);
        //    BaseViewModel bvm = icv.DataContext as BaseViewModel;
        //    TopicCard ic = bvm.Model as TopicCard;
        //    Card c = bvm.Model as Card;

        //    ZInformationLandscape zil = ZTreeHelper.TryFindParent<ZInformationLandscape>(icv);
        //    Grid mainGrid = (((zil.Parent as RootCollectionView).Parent as Grid).Parent as Grid); // gets the mainGrid
        //    UIElementCollection elCol = mainGrid.Children;
        //    IEnumerable<Image> images = elCol.OfType<Image>();

        //    Image imgOverview = images.Where(x => x.Uid == "4").Single(); // for the overview image back_silver.jpg
        //    String test = c.CategoryID.ToString();
        //    Image imgCategory = images.Where(x => x.Uid == (c.CategoryID.ToString())).Single();

        //    // animation, opacity change of background --> just a hack
        //    double start = 0.0;
        //    double stop = 1.0;

        //    Duration dur = new Duration(TimeSpan.FromSeconds(1));

        //    DoubleAnimation animForward = new DoubleAnimation(start, stop, dur);
        //    DoubleAnimation animBackward = new DoubleAnimation(stop, start, dur);

        //    Storyboard storyboard = new Storyboard();

        //    Storyboard.SetTargetName(animForward, imgCategory.Name);
        //    Storyboard.SetTargetProperty(animForward, new PropertyPath(Image.OpacityProperty));

        //    Storyboard.SetTargetName(animBackward, imgOverview.Name);
        //    Storyboard.SetTargetProperty(animBackward, new PropertyPath(Image.OpacityProperty));

        //    storyboard.Children.Add(animForward);
        //    storyboard.Children.Add(animBackward);

        //    storyboard.Begin((imgCategory as FrameworkElement));
        //    storyboard.Begin((imgOverview as FrameworkElement));

        //    //zil.ZoomOnto(c.ParentZComponent, false, true);
        //}

        void TopicCardView_Loaded(object sender, RoutedEventArgs e)
        {
            imageRectangle.IsVisibleChanged += new DependencyPropertyChangedEventHandler(img_IsVisibleChanged);
        }

        void img_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue.Equals(true))
            {
                    TopicCardViewModel imgCVM = (TopicCardViewModel)DataContext;
                    if (imgCVM != null)
                        ThreadPool.QueueUserWorkItem(LoadImage, imgCVM.TextureUrl.ToString());
            }
            else
            {
                imageBrush.ImageSource = null;
                GC.Collect();
            }
        }

        public void LoadImage(object path)
        {
            //return if null value are file doesn't exists
            Uri uri = new Uri(path.ToString());
            MemoryStream mem = null;
            BitmapDecoder decoder = null;
            //try to load image
            try
            {
                //load into memory
                //synchronze file access -> massive sequential seems to be faster
                byte[] buffer = null;
                Monitor.Enter(CardUtil.FileLoadMonitor);
                try
                {
                    if (File.Exists(uri.LocalPath))
                        buffer = File.ReadAllBytes(uri.LocalPath);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex);
                }
                Monitor.Exit(CardUtil.FileLoadMonitor);

                if (buffer == null)
                    return;

                mem = new MemoryStream(buffer);
                //bitmapdecode
                decoder = BitmapDecoder.Create(uri, BitmapCreateOptions.None, BitmapCacheOption.Default);
                if (decoder != null)
                {
                    BitmapFrame frame = (decoder as BitmapDecoder).Frames.First();
                    //load thumbnail
                    //if (frame.Thumbnail != null)
                    //{
                    //    this.Dispatcher.Invoke(DispatcherPriority.Send, new Action<ImageSource>(SetImage), frame.Thumbnail);
                    //    return;
                    //}
                    //scale down if too big
                    if (frame.Width > CardUtil.MaxCachedImageSize || frame.Height > CardUtil.MaxCachedImageSize)
                    {
                        TransformedBitmap scaledImage = new TransformedBitmap();
                        scaledImage.BeginInit();
                        scaledImage.Source = frame as BitmapSource;

                        // we'll make a reasonable sized thumnbail with a height of 240
                        int pixelH = frame.PixelHeight;
                        int pixelW = frame.PixelWidth;
                        int decodeW;
                        int decodeH;
                        if (frame.PixelWidth > frame.PixelHeight)
                        {
                            decodeW = CardUtil.MaxCachedImageSize;
                            decodeH = (frame.PixelHeight * decodeW) / pixelW;
                        }
                        else
                        {
                            decodeH = CardUtil.MaxCachedImageSize;
                            decodeW = (frame.PixelWidth * decodeH) / pixelH;
                        }
                        double scaleX = decodeW / (double)pixelW;
                        double scaleY = decodeH / (double)pixelH;
                        TransformGroup transformGroup = new TransformGroup();
                        transformGroup.Children.Add(new ScaleTransform(scaleX, scaleY));
                        scaledImage.Transform = transformGroup;
                        scaledImage.EndInit();
                        // this will disconnect the stream from the image completely ...
                        WriteableBitmap writable = new WriteableBitmap(scaledImage);
                        writable.Freeze();
                        this.Dispatcher.Invoke(DispatcherPriority.Send, new Action<ImageSource>(SetImage), writable);
                    }
                    else
                    {
                        //load full original image
                        this.Dispatcher.Invoke(DispatcherPriority.Send, new Action<ImageSource>(SetImage), frame);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }
            finally
            {
                if (mem != null)
                    mem.Close();
            }
        }

        public void SetImage(ImageSource source)
        {
            imageBrush.ImageSource = source;
        }

        private void ZComponent_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ((Storyboard)FindResource("MouseDownStoryBoard")).Begin();
        }

        private void ZComponent_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ((Storyboard)FindResource("MouseUpStoryBoard")).Begin();
        }

        private void HandleTabOnButton(object sender, Microsoft.Surface.Presentation.ContactEventArgs e)
        {
            e.Handled = true;
        }
    }
}
